package com.huawei.aw;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * AWHttpUtil（Auto Wrapper HTTP Utility）
 * 项目：mes-spw-aw（Gitee: https://gitee.com/songcqs/mes-spw-aw.git）
 * 功能：封装常用 HTTP 请求（GET / POST / PUT），返回完整请求/响应上下文。
 * 特点：
 * - 基于 Java 11+ 内置 HttpClient，无第三方依赖（除 Jackson 外）
 * - 自动过滤 Java HttpClient 禁止设置的受限头（如 Connection, Host）
 * - 支持传入 Map<String, String> 作为请求头
 * - 自动将 Object 序列化为 JSON（POST/PUT）
 * - 返回 AWHttpResponse 对象，包含请求头、请求体、响应头、响应体等
 */
public class AWHttpUtilBody {

    // JSON 序列化工具（线程安全）
    private static final ObjectMapper objectMapper = new ObjectMapper();

    // 全局复用的 HttpClient（线程安全）
    private static final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    // Java HttpClient 禁止手动设置的请求头（大小写不敏感）
    private static final Set<String> RESTRICTED_HEADERS = new HashSet<>(Arrays.asList(
            "connection", "host", "content-length", "upgrade",
            "transfer-encoding", "keep-alive", "proxy-connection"
    ));

    /**
     * 安全设置请求头：跳过受限头，并返回实际设置的 headers（用于记录）
     *
     * @param builder  HttpRequest.Builder
     * @param headers  用户传入的 headers
     * @return 实际被设置的 headers（不含受限头）
     */
    private static Map<String, String> safeSetHeaders(HttpRequest.Builder builder, Map<String, String> headers) {
        Map<String, String> actualHeaders = new HashMap<>();
        if (headers == null || headers.isEmpty()) {
            return actualHeaders;
        }
        headers.forEach((name, value) -> {
            if (name != null && value != null) {
                String lowerName = name.toLowerCase().trim();
                if (!RESTRICTED_HEADERS.contains(lowerName)) {
                    builder.header(name, value);
                    actualHeaders.put(name, value);
                }
            }
        });
        return actualHeaders;
    }

    // ==================== GET 请求 ====================

    /**
     * 发送 GET 请求（无自定义头）
     */
    public static AWHttpResponse get(String url) throws Exception {
        return get(url, null);
    }

    /**
     * 发送 GET 请求（带自定义头）
     */
    public static AWHttpResponse get(String url, Map<String, String> headers) throws Exception {
        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(30))
                .GET();

        Map<String, String> actualHeaders = safeSetHeaders(requestBuilder, headers);
        HttpRequest request = requestBuilder.build();

        HttpResponse<String> httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // 将响应头转换为 Map<String, String>（多值用逗号连接）
        Map<String, String> responseHeaders = httpResponse.headers().map().entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        e -> String.join(", ", e.getValue())
                ));

        return new AWHttpResponse(
                url,
                "GET",
                actualHeaders,
                null,
                httpResponse.statusCode(),
                responseHeaders,
                httpResponse.body()
        );
    }

    // ==================== POST 请求 ====================

    /**
     * 发送 POST 请求（自动序列化 body 为 JSON）
     */
    public static AWHttpResponse post(String url, Object body) throws Exception {
        return post(url, body, null);
    }

    /**
     * 发送 POST 请求（带自定义头）
     */
    public static AWHttpResponse post(String url, Object body, Map<String, String> headers) throws Exception {
        String jsonBody = body instanceof String ? (String) body : objectMapper.writeValueAsString(body);

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(30))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonBody));

        // 记录 Content-Type 和用户自定义头（过滤后）
        Map<String, String> actualHeaders = new HashMap<>();
        actualHeaders.put("Content-Type", "application/json");
        actualHeaders.putAll(safeSetHeaders(requestBuilder, headers));

        HttpRequest request = requestBuilder.build();
        HttpResponse<String> httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        Map<String, String> responseHeaders = httpResponse.headers().map().entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        e -> String.join(", ", e.getValue())
                ));

        return new AWHttpResponse(
                url,
                "POST",
                actualHeaders,
                jsonBody,
                httpResponse.statusCode(),
                responseHeaders,
                httpResponse.body()
        );
    }

    // ==================== PUT 请求 ====================

    /**
     * 发送 PUT 请求（自动序列化 body 为 JSON）
     */
    public static AWHttpResponse put(String url, Object body) throws Exception {
        return put(url, body, null);
    }

    /**
     * 发送 PUT 请求（带自定义头）
     */
    public static AWHttpResponse put(String url, Object body, Map<String, String> headers) throws Exception {
        String jsonBody = body instanceof String ? (String) body : objectMapper.writeValueAsString(body);

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(30))
                .header("Content-Type", "application/json")
                .PUT(HttpRequest.BodyPublishers.ofString(jsonBody));

        Map<String, String> actualHeaders = new HashMap<>();
        actualHeaders.put("Content-Type", "application/json");
        actualHeaders.putAll(safeSetHeaders(requestBuilder, headers));

        HttpRequest request = requestBuilder.build();
        HttpResponse<String> httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        Map<String, String> responseHeaders = httpResponse.headers().map().entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        e -> String.join(", ", e.getValue())
                ));

        return new AWHttpResponse(
                url,
                "PUT",
                actualHeaders,
                jsonBody,
                httpResponse.statusCode(),
                responseHeaders,
                httpResponse.body()
        );
    }
}